<?php

namespace App\Http\Repositories\Order;

use App\Http\Repositories\Demand\DemandRepo;
use App\Http\Repositories\Relation\OrderObjectRepo;
use App\Http\Repositories\Repository;
use App\Http\Repositories\Service\ServiceRepo;
use App\Models\Order;
use App\Traits\HelpFunctions;
use Illuminate\Support\Facades\DB;

/**
 * 订单相关
 */
class OrderRepo extends Repository
{
    use HelpFunctions;

    const MODEL = Order::class;

    public function search(array $params)
    {
        $query = $this->query()
            ->select(
                "orders.*",
                "orders.id as order_id",
                "orders.created_at as order_created_at",
                "users.name",
                "order_object_relation.type"
            )
            ->leftJoin('order_object_relation', 'order_object_relation.order_id', '=', 'orders.id')
            ->leftJoin('users', 'users.id', '=', 'order_object_relation.user_id');

        if (!empty($params['user_name'])) {
            $query->where('user_name', 'like', '%' . $params['user_name'] . '%');
        }
        if (!empty($params['order_sn'])) {
            $query->where('order_sn', 'like', '%' . $params['order_sn'] . '%');
        }
        if (!empty($params['order_id'])) {
            $query->where('order_id', $params['order_id']);
        }
        if (!empty($params['order_status'])) {
            $query->where('order_status', $params['order_status']);
        }
        if (!empty($params['type'])) {
            $query->where('type', $params['type']);
        }

        if (!empty($params['begin_time'])) {
            $query->where('order_created_at', '>=', $params['begin_time']);
        }
        if (!empty($params['end_time'])) {
            $query->where('order_created_at', '<=', $params['end_time']);
        }

        $query->with('demands')
            ->with('services');

        return $this->paginate($query, $params["paginate"] ?? true, $params["page_num"] ?? 10);
    }

    public function getOneById($order_id)
    {
        $query = $this->query()
            ->select(
                "orders.*",
                "orders.id as order_id",
                "orders.created_at as order_created_at",
                "users.name",
                "order_object_relation.type"
            )
            ->leftJoin('order_object_relation', 'order_object_relation.order_id', '=', 'orders.id')
            ->leftJoin('users', 'users.id', '=', 'order_object_relation.user_id')
            ->with('demands')
            ->with('services')
            ->first();

        return !empty($query) ? $query->toArray() : [];
    }

    public function createOne(array $params)
    {
        //Order参数
        $args = $this->getOrderArgs($params);
        $object = $this->getObject($args['object_id'], $args['type']);
        $order_args = [
            'order_sn' => $args['sn'],
            'amount' => $object['price'],
            'created_at' => $args['created_at'],
        ];

        //事务处理
        DB::beginTransaction();

        try {
            //添加order数据
            $order = parent::createOne($order_args);
            $order_id = $order->id;

            //添加order_object数据
            $order_object_args = [
                'user_id' => $args['user_id'],
                'object_id' => $args['object_id'],
                'type' => $args['type'],
                'order_id' => $order_id,
            ];
            app(OrderObjectRepo::class)->createOne($order_object_args);

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            abort(500, $e->getMessage());
        }
        return $this->getOneById($order_id, $args['type']);
    }

    private function getObject($object_id, $type)
    {
        if ($type == 1) {
            return app(ServiceRepo::class)->getOneById($object_id);
        }
        return app(DemandRepo::class)->getOneById($object_id);
    }

    public function deleteById(int $id)
    {
        DB::beginTransaction();
        try {
            $order = $this->getOneById($id);
            parent::deleteById($id);

            app(OrderObjectRepo::class)->deleteByConditions(['order_id' => $id]);

            DB::commit();

            return true;
        } catch (\Exception $e) {
            DB::rollBack();
            abort(500, $e->getMessage());
        }
    }
}
